﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace avs2bdnxml_gui
{
    #region Class Shell

    public class Shell
    {
        #region Members

        private readonly Process _process;

        public string FileName { get; }
        public string Args { get; }
        public string WorkDir { get; }
        public bool HasExited => this._process.HasExited;
        public List<int> ProcessId { get; set; }

        #endregion

        #region Constructor

        public Shell(string filename, string args, string workdir, DataReceivedEventHandler outputDataReceived)
        {
            this.FileName = filename;
            this.Args = args;
            this.WorkDir = workdir;
            this.ProcessId = new List<int>();
            this._process = new Process
            {
                StartInfo =
                {
                    FileName = this.FileName,
                    Arguments = this.Args,
                    WorkingDirectory = this.WorkDir,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                }
            };
            this._process.OutputDataReceived += outputDataReceived;
            this._process.ErrorDataReceived += outputDataReceived;
        }

        #endregion

        #region Methods

        public void Start()
        {
            try
            {
                this._process.Start();
                this._process.BeginOutputReadLine();
                this._process.BeginErrorReadLine();
                this.ProcessId.Add(this._process.Id);
                Console.WriteLine(@"start:" + this._process.Id);
                this._process.WaitForExit();
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine(e.Message);
            }
        }

        public void Stop()
        {
            try
            {
                this._process.Kill();
                this._process.CancelOutputRead();
                this._process.CancelErrorRead();
                this._process.Dispose();
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (Win32Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        public void BatchStop()
        {
            RunCmd("taskkill /im avs2bdnxml.exe /f");
        }

        /// <summary>    
        /// 运行DOS命令    
        /// DOS关闭进程命令(ntsd -c q -p PID )PID为进程的ID    
        /// </summary>    
        /// <param name="command"></param>    
        /// <returns></returns>    
        public static string RunCmd(string command)
        {
            //實例一個Process類，啟動一個獨立進程    
            var p = new Process
            {
                StartInfo =
                {
                    FileName = "cmd.exe",
                    Arguments = "/c " + command,
                    UseShellExecute = false,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            //Process類有一個StartInfo屬性，這個是ProcessStartInfo類，包括了一些屬性和方法，下面我們用到了他的幾個屬性：    

            //設定程序名    
            //設定程式執行參數    
            //關閉Shell的使用    
            //重定向標準輸入    
            //重定向標準輸出    
            //重定向錯誤輸出    
            //設置不顯示窗口    

            p.Start(); //啟動    

            //p.StandardInput.WriteLine(command);       //也可以用這種方式輸入要執行的命令    
            //p.StandardInput.WriteLine("exit");        //不過要記得加上Exit要不然下一行程式執行的時候會當機    

            return p.StandardOutput.ReadToEnd(); //從輸出流取得命令執行結果    
        }

        #endregion
    }

    #endregion
}